package com.ruoyi.background.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.background.domain.*;
import com.ruoyi.background.service.IAppGradeRecordService;
import com.ruoyi.background.service.IAppWechatStepService;
import com.ruoyi.background.service.IAppWechatUserService;
import com.ruoyi.background.service.IWechatApiService;
import com.ruoyi.background.utils.REDIS_KEY;
import com.ruoyi.background.utils.WechatConstant;
import com.ruoyi.background.utils.WechatUtils;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


@Service
public class WechatApiServiceImpl implements IWechatApiService {


    @Autowired
    private IAppWechatUserService wechatUserService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IAppWechatStepService wechatStepService;

    @Autowired
    private IAppGradeRecordService gradeRecordService;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private SysLoginService sysLoginService;


    /**
     * 获取用户openid
     *
     * @param code code
     * @return 结果
     */
    @Override

    public AppWechatUser getUserOpenId(String code) {
        String params = "appid=" + WechatConstant.WECHAT_APPID + "&secret=" + WechatConstant.WECHAT_APP_SECRET + "&js_code=" + code + "&grant_type=authorization_code";
        String s = HttpUtils.sendGet(WechatConstant.WECHAT_AUTH_URL, params);
        if (ObjectUtils.isEmpty(s)) throw new RuntimeException("微信授权失败！");
        JSONObject jsonObject = JSONObject.parseObject(s);
        String openid = jsonObject.getString("openid");
        String sessionKey = jsonObject.getString("session_key");
        if (ObjectUtils.isEmpty(openid)) throw new RuntimeException("微信授权失败！");
        //根据openid查询
        AppWechatUser wechatUser = wechatUserService.selectAppWechatByOpenid(openid);
        if (ObjectUtils.isEmpty(wechatUser)) {
            wechatUser = new AppWechatUser();
            wechatUser.setLastLoginTime(DateUtils.getNowDate());
            wechatUser.setOpenid(openid);
            wechatUser.setSessionKey(sessionKey);
            wechatUser.setCreateTime(DateUtils.getNowDate());
            int i = wechatUserService.insertAppWechatUser(wechatUser);
            if (i > 0) return wechatUser;
            else throw new RuntimeException("微信授权失败！");
        } else {
            AppWechatUser update = new AppWechatUser();
            update.setId(wechatUser.getId());
            update.setSessionKey(sessionKey);
            update.setLastLoginTime(DateUtils.getNowDate());
            int i = wechatUserService.updateAppWechatUser(update);
            if (i > 0) return wechatUser;
            else throw new RuntimeException("微信授权失败！");
        }
    }

    /**
     * 更新sessionKey
     *
     * @param code code
     * @return 结果
     */
    @Override
    public int updateSessionKey(String code) {
        String params = "appid=" + WechatConstant.WECHAT_APPID + "&secret=" + WechatConstant.WECHAT_APP_SECRET + "&js_code=" + code + "&grant_type=authorization_code";
        String s = HttpUtils.sendGet(WechatConstant.WECHAT_AUTH_URL, params);
        if (ObjectUtils.isEmpty(s)) throw new RuntimeException("微信授权失败！");
        JSONObject jsonObject = JSONObject.parseObject(s);
        String openid = jsonObject.getString("openid");
        String sessionKey = jsonObject.getString("session_key");
        if (ObjectUtils.isEmpty(openid)) throw new RuntimeException("微信授权失败！");
        //根据openid查询
        AppWechatUser wechatUser = wechatUserService.selectAppWechatByOpenid(openid);
        if (ObjectUtils.isEmpty(wechatUser))
            throw new RuntimeException("请重新登录！");
        if (ObjectUtils.isEmpty(wechatUser.getUserId()) || ObjectUtils.isEmpty(wechatUser.getPhoneNumber())) {
            throw new RuntimeException("账号信息为空，请重新登录！");
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String nowFormat = simpleDateFormat.format(DateUtils.getNowDate());
        String lastFormat = simpleDateFormat.format(wechatUser.getLastLoginTime());
        if (!nowFormat.equals(lastFormat)) {
            this.addUserLoginGrade(wechatUser);
        }
        AppWechatUser update = new AppWechatUser();
        update.setId(wechatUser.getId());
        update.setSessionKey(sessionKey);
        update.setLastLoginTime(DateUtils.getNowDate());
        return wechatUserService.updateAppWechatUser(update);
    }

    @Override
    public List<String> createTokens(AppWechatUser wechatUser) {
        List<AppWechatUser> userList = wechatUserService.selectAppWechatUserList(wechatUser);
        List<String> tokens = new ArrayList<>();
        int i = 0;
        for (AppWechatUser wechatUser1 : userList) {
            if (ObjectUtils.isEmpty(wechatUser1) || wechatUser1.getUserId() == null)
                continue;
            SysUser user = sysUserService.selectUserByPhone(wechatUser1.getPhoneNumber());
            String token = sysLoginService.wechatLogin(user);
            tokens.add(token);
            i++;
            if (i > 301) break;
        }
        return tokens;
    }


    /**
     * 首次登录奖励
     *
     * @param wechatUser 用户信息
     */
    @Async
    @Transactional
    public void addUserLoginGrade(AppWechatUser wechatUser) {
        int s = Integer.parseInt(configService.selectConfigByKey("app.grade.first"));
        AppGradeRecord record = new AppGradeRecord();
        record.setUserId(wechatUser.getUserId());
        record.setGrade(s);
        record.setType(0);
        record.setBeforeGrade(wechatUser.getGrade());
        record.setCreateTime(DateUtils.getNowDate());
        record.setRemark("每天首次登录奖励");
        gradeRecordService.insertAppGradeRecord(record);
        AppWechatUser update = new AppWechatUser();
        update.setId(wechatUser.getId());
        update.setGrade(wechatUser.getGrade() + s);
        wechatUserService.updateAppWechatUser(update);
    }


    /**
     * 获取用户手机号
     *
     * @param wechatPhone 小程序参数
     * @return 结果
     */
    @Override
    public AppWechatUser getUserPhone(WechatPhone wechatPhone) {
        String accessToken = this.getAccessToken();
        if (ObjectUtils.isEmpty(accessToken)) throw new RuntimeException("获取accessToken失败！");
        String url = WechatConstant.WECHAT_PHONE_URL + "?access_token=" + accessToken;
        JSONObject param = JSON.parseObject("{'code':'" + wechatPhone.getCode() + "'}");
        String data = HttpUtils.sendJsonPost(url, param);
        JSONObject res = JSON.parseObject(data);
        if (!"0".equalsIgnoreCase(res.getString("errcode"))) {
            throw new RuntimeException("系统繁忙！");
        }
        if (!res.containsKey("phone_info")) {
            throw new RuntimeException("微信无绑定手机号！");
        }
        JSONObject phoneInfo = res.getJSONObject("phone_info");
        if (!phoneInfo.containsKey("phoneNumber") || ObjectUtils.isEmpty(phoneInfo.getString("phoneNumber"))) {
            throw new RuntimeException("用户未绑定手机号!");
        }
        String userPhone = phoneInfo.getString("purePhoneNumber");
        AppWechatUser wechatUser = wechatUserService.selectAppWechatByOpenid(wechatPhone.getOpenid());
        wechatUser.setPhoneNumber(userPhone);
        return wechatUser;
    }

    /**
     * 节目微信运动数据
     *
     * @param step 加密数据
     * @return 结果
     */
    @Override
    public AppWechatStep getUserStepList(WechatPhone step) {
        //去sessionKey
        AppWechatUser wechatUser = wechatUserService.selectAppWechatByUserId();
        //先取缓存
        Object cacheObject = redisCache.getCacheObject(wechatUser.getOpenid() + "wechat_step_data_today");
        if (!ObjectUtils.isEmpty(cacheObject))
            return wechatStepService.getTodayStepRowByUserId();
        // 缓存没有就解密数据
        String runData = WechatUtils.wxDecrypt(step.getEncryptedData(), wechatUser.getSessionKey(), step.getIv());
        if (ObjectUtils.isEmpty(runData)) throw new RuntimeException("获取微信步数失败，请向管理员反馈！");
        //解析数据
        this.parseRunData(runData, wechatUser);
        return wechatStepService.getTodayStepRowByUserId();
    }

    /**
     * 获取微信历史步数
     *
     * @return
     */
    @Override
    public List<WechatStep> getUserWechatHistory() {
        AppWechatUser wechatUser = wechatUserService.selectAppWechatByUserId();
        String cacheObject = redisCache.getCacheObject(wechatUser.getOpenid() + "wechat_step_data");
        if (ObjectUtils.isEmpty(cacheObject)) throw new RuntimeException("获取微信历史步数失败！");
        JSONObject jsonObject = JSON.parseObject(cacheObject);
        JSONArray array = jsonObject.getJSONArray("stepInfoList");
        List<WechatStep> list = new ArrayList<>();
        for (int i = 0; i < array.size(); i++) {
            WechatStep wechatStep = new WechatStep();
            JSONObject temp = array.getJSONObject(i);
            Integer step = temp.getInteger("step");
            Long timestamp = temp.getLong("timestamp");
            wechatStep.setStep(step);
            wechatStep.setTimestamp(timestamp * 1000);
            wechatStep.setRowData(DateUtils.parseDateToStr("yyyy-MM-dd", new Date(wechatStep.getTimestamp())));
            list.add(wechatStep);
        }
        list = list.stream().sorted((a, b) -> b.getTimestamp().compareTo(a.getTimestamp())).collect(Collectors.toList());
        return list;
    }

    /**
     * 解析微信运动的数据
     *
     * @param runData 解密微信运动的数据
     */
    public void parseRunData(String runData, AppWechatUser wechatUser) {
        JSONObject jsonObject = JSON.parseObject(runData);
        JSONArray array = jsonObject.getJSONArray("stepInfoList");
        List<WechatStep> list = new ArrayList<>();
        for (int i = 0; i < array.size(); i++) {
            JSONObject temp = array.getJSONObject(i);
            Integer step = temp.getInteger("step");
            Long timestamp = temp.getLong("timestamp");
            WechatStep wechatStep = new WechatStep();
            wechatStep.setStep(step);
            wechatStep.setTimestamp(timestamp * 1000);
            wechatStep.setRowData(DateUtils.parseDateToStr("yyyy-MM-dd", new Date(wechatStep.getTimestamp())));
            list.add(wechatStep);
        }
        //写入缓存 不设置过期的时间 为了历史数据使用
        String allKey = wechatUser.getOpenid() + REDIS_KEY.USER_STEP_ALL_LIST_KEY;
        String todayKey = wechatUser.getOpenid() + REDIS_KEY.USER_STEP_TODAY_KEY;
        redisCache.setCacheObject(allKey, runData);
        //按日期排序
        list = list.stream().sorted((a, b) -> b.getTimestamp().compareTo(a.getTimestamp())).collect(Collectors.toList());
        //返回今天的数据
        WechatStep wechatStep = list.get(0);
        int todayStep = ObjectUtils.isEmpty(wechatStep.getStep()) ? 1 : wechatStep.getStep();
        if (SecurityUtils.getUserId() == 100) todayStep = 14000;
        //设置今天的微信步数 缓存 10 分钟
        redisCache.setCacheObject(todayKey, todayStep);
        redisCache.expire(todayKey, 10 * 60);
        this.updateUserTodayStep(todayStep);
    }

    /**
     * 更新用户数据库的数据
     *
     * @param step 步数
     */
    public void updateUserTodayStep(Integer step) {
        //查找今天是否有步数记录
        AppWechatStep todayData = wechatStepService.getTodayStepRowByUserId();
        if (ObjectUtils.isEmpty(todayData)) {
            AppWechatStep wechatStep = new AppWechatStep();
            wechatStep.setUserId(SecurityUtils.getUserId());
            wechatStep.setDeptId(SecurityUtils.getDeptId());
            wechatStep.setWechatStep(step);
            wechatStep.setRecordDate(DateUtils.getNowDate());
            wechatStepService.insertAppWechatStep(wechatStep);
        } else {
            AppWechatStep wechatStep = new AppWechatStep();
            wechatStep.setId(todayData.getId());
            wechatStep.setWechatStep(step);
            wechatStepService.updateAppWechatStep(wechatStep);
        }
    }


    /**
     * 获取小程序的accessToken
     *
     * @return 结果
     */
    @Override
    public String getAccessToken() {
        String ACCESS_TOKEN = redisCache.getCacheObject("APPLET_ACCESS_TOKEN");
        if (null == ACCESS_TOKEN || "".equalsIgnoreCase(ACCESS_TOKEN) || ObjectUtils.isEmpty(ACCESS_TOKEN)) {
            String tokenUrl = WechatConstant.WECHAT_ACCESS_TOKEN_URL + "&appid=" + WechatConstant.WECHAT_APPID + "&secret=" + WechatConstant.WECHAT_APP_SECRET;
            String tokenData = HttpUtils.sendGet(tokenUrl);
            JSONObject tokenJsonData = JSONObject.parseObject(tokenData);
            ACCESS_TOKEN = tokenJsonData.getString("access_token");
            String key = REDIS_KEY.APPLET_ACCESS_TOKEN;
            redisCache.setCacheObject(key, ACCESS_TOKEN);
            redisCache.expire(key, 7000);
        }
        return ACCESS_TOKEN;
    }


}
